package brinaryTree;

/**
 * 450. 删除二叉搜索树中的节点
 * <p>
 * 给定一个二叉搜索树的根节点 root 和一个值 key，删除二叉搜索树中的 key 对应的节点，并保证二叉搜索树的性质不变。返回二叉搜索树（有可能被更新）的根节点的引用。
 * <p>
 * 一般来说，删除节点可分为两个步骤：
 * <p>
 * 首先找到需要删除的节点；
 * <p>
 * 如果找到了，删除它。
 */
public class N450_DeleteNodeInBST {
    public TreeNode deleteNode(TreeNode root, int key) {
        if (root == null) return null;
        if (root.val == key) {
            if (root.left == null) return root.right;
            if (root.right == null) return root.left;
            else {
                TreeNode cur = root.right;
                while (cur.left != null) cur = cur.left;
                cur.left = root.left;
                return root.right;
            }
        }
        if (root.val > key) root.left = deleteNode(root.left, key);
        else root.right = deleteNode(root.right, key);
        return root;
    }

    public TreeNode deleteNode_Iter(TreeNode root, int key) {
        if (root == null) return root;
        TreeNode cur = root;
        TreeNode pre = null;
        while (cur != null) {
            if (cur.val == key) break;
            pre = cur;
            if (cur.val > key) cur = cur.left;
            else cur = cur.right;
        }
        if (pre == null) return deleteOneNode(cur);
        if (pre.left != null && pre.left.val == key) pre.left = deleteOneNode(cur);
        if (pre.right != null && pre.right.val == key) pre.right = deleteOneNode(cur);
        return root;
    }

    private TreeNode deleteOneNode(TreeNode target) {
        if (target == null) return target;
        if (target.right == null) return target.left;
        TreeNode cur = target.right;
        while (cur.left != null) cur = cur.left;
        cur.left = target.left;
        return target.right;
    }

}
